package com.example.gobang.test;

/**
 * AI下棋算法-第一次的尝试,非常呆
 */
public class GobangAI {

    private static final int AI_PLAYER = 2;
    private static final int HUMAN_PLAYER = 1;
    private static final int EMPTY = 0;

    public int[] findBestMove(int[][] board, int maxDepth) {
        int[] bestMove = null;

        for (int depth = 1; depth <= maxDepth; depth++) {
            int[] result = minimax(board, depth, Integer.MIN_VALUE, Integer.MAX_VALUE, true);
            bestMove = new int[]{result[1], result[2]};

            // 如果满足终止条件，退出循环
            if (result[0] == Integer.MAX_VALUE || result[0] == Integer.MIN_VALUE) {
                break;
            }
        }

        return bestMove;
    }


    private int[] minimax(int[][] board, int depth, int alpha, int beta, boolean maximizingPlayer) {
        int currentPlayer = maximizingPlayer ? AI_PLAYER : HUMAN_PLAYER;

        int[] bestMove = new int[]{-1, -1, -1}; // [score, row, col]

        if (depth == 0 || isGameOver(board)) {
            bestMove[0] = evaluate(board);
            return bestMove;
        }

        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[i].length; j++) {
                if (board[i][j] == EMPTY) {
                    board[i][j] = currentPlayer;

                    int[] result = minimax(board, depth - 1, alpha, beta, !maximizingPlayer);
                    int score = result[0];

                    board[i][j] = EMPTY;

                    if (maximizingPlayer && score > alpha) {
                        alpha = score;
                        bestMove = new int[]{score, i, j};
                    } else if (!maximizingPlayer && score < beta) {
                        beta = score;
                        bestMove = new int[]{score, i, j};
                    }

                    if (alpha >= beta) {
                        break; // Alpha-Beta剪枝
                    }
                }
            }
        }

        return bestMove;
    }



    private boolean isGameOver(int[][] board) {
        // 判断行、列、对角线是否有五子连珠
        if (checkWinInRows(board) || checkWinInColumns(board) || checkWinInDiagonals(board)) {
            return true;
        }

        // 判断棋盘是否已满
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[i].length; j++) {
                if (board[i][j] == EMPTY) {
                    return false; // 存在空位置，游戏未结束
                }
            }
        }
        return true; // 棋盘已满，游戏结束
    }

    private boolean checkWinInRows(int[][] board) {
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j <= board[i].length - 5; j++) {
                if (board[i][j] != EMPTY &&
                    board[i][j] == board[i][j + 1] &&
                    board[i][j] == board[i][j + 2] &&
                    board[i][j] == board[i][j + 3] &&
                    board[i][j] == board[i][j + 4]) {
                    return true; // 有五子连珠
                }
            }
        }
        return false;
    }

    private boolean checkWinInColumns(int[][] board) {
        for (int j = 0; j < board[0].length; j++) {
            for (int i = 0; i <= board.length - 5; i++) {
                if (board[i][j] != EMPTY &&
                    board[i][j] == board[i + 1][j] &&
                    board[i][j] == board[i + 2][j] &&
                    board[i][j] == board[i + 3][j] &&
                    board[i][j] == board[i + 4][j]) {
                    return true; // 有五子连珠
                }
            }
        }
        return false;
    }

    private boolean checkWinInDiagonals(int[][] board) {
        for (int i = 0; i <= board.length - 5; i++) {
            for (int j = 0; j <= board[i].length - 5; j++) {
                if (board[i][j] != EMPTY &&
                    (board[i][j] == board[i + 1][j + 1] &&
                    board[i][j] == board[i + 2][j + 2] &&
                    board[i][j] == board[i + 3][j + 3] &&
                    board[i][j] == board[i + 4][j + 4])) {
                    return true; // 有五子连珠
                }

                if (board[i][j + 4] != EMPTY &&
                    (board[i][j + 4] == board[i + 1][j + 3] &&
                    board[i][j + 4] == board[i + 2][j + 2] &&
                    board[i][j + 4] == board[i + 3][j + 1] &&
                    board[i][j + 4] == board[i + 4][j])) {
                    return true; // 有五子连珠
                }
            }
        }
        return false;
    }

    private int evaluate(int[][] board) {
        int score = 0;

        // 遍历每个位置
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[i].length; j++) {
                if (board[i][j] == AI_PLAYER) {
                    score += evaluatePosition(board, i, j, AI_PLAYER); // 计算AI的得分
                } else if (board[i][j] == HUMAN_PLAYER) {
                    score -= evaluatePosition(board, i, j, HUMAN_PLAYER); // 计算玩家的得分
                }
            }
        }

        return score;
    }

    // 评估每个位置的得分
    private int evaluatePosition(int[][] board, int row, int col, int player) {
        int score = 0;

        // 水平、垂直、对角线上的棋型
        int[] dx = {0, 1, 1, 1};
        int[] dy = {1, 0, 1, -1};

        for (int d = 0; d < 4; d++) {
            int count = 0; // 连续棋子的数量
            int empty = 0; // 两端的空位数量

            for (int k = -4; k <= 4; k++) {
                int ni = row + k * dx[d];
                int nj = col + k * dy[d];

                if (ni >= 0 && ni < board.length && nj >= 0 && nj < board[0].length) {
                    if (board[ni][nj] == player) {
                        count++;
                    } else if (board[ni][nj] == EMPTY) {
                        empty++;
                    }
                }
            }

            score += evaluatePattern(count, empty);
        }

        return score;
    }

    // 根据棋型和空位数量计算得分
    private int evaluatePattern(int count, int empty) {
        if (count == 5) {
            return 10000; // 五子连珠，最高分
        } else if (count == 4) {
            if (empty == 2) {
                return 1000; // 活四
            } else if (empty == 1) {
                return 100; // 冲四
            }
        } else if (count == 3) {
            if (empty == 2) {
                return 100; // 活三
            } else if (empty == 1) {
                return 10; // 冲三
            }
        } else if (count == 2 && empty == 2) {
            return 10; // 活二
        }

        return 0; // 其他情况得分为0
    }

    public static void main(String[] args) {
        GobangAI ai = new GobangAI();

        // 示例：创建一个15x15的棋盘
        int[][] board = new int[15][15];

        // 在此处添加玩家的落子，例如：board[7][7] = HUMAN_PLAYER;
        board[7][7] = HUMAN_PLAYER;
        board[7][1] = AI_PLAYER;
        board[7][8] = HUMAN_PLAYER;
        board[1][1] = AI_PLAYER;
        board[0][0] = AI_PLAYER;
        board[7][9] = HUMAN_PLAYER;
        // 调用AI算法找到最佳位置
        int[] bestMove = ai.findBestMove(board,4);

        // 输出AI的最佳位置
        System.out.println("AI's Best Move - Row: " + bestMove[0] + ", Col: " + bestMove[1]);
    }
}
